package com.beyond.framework.privilege;

import com.beyond.framework.privilege.annotations.Privilege;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Created by IntelliJ IDEA.
 * User: lewisw
 * Date: Sep 19, 2010
 * Time: 2:31:00 PM
 */
public class PrivilegeReader {

    public static final String PRIVILEGE_RESOURCE_SUFFIX = ".class";

    public static final String DEFAULT_MATCH_PATTERN = "**/domain/**/*" + PRIVILEGE_RESOURCE_SUFFIX;

    private String locationPattern = DEFAULT_MATCH_PATTERN;

    private static final ResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver();

    private static final MetadataReaderFactory READER_FACTORY = new SimpleMetadataReaderFactory();

    public void setLocationPattern(String locationPattern) {
        this.locationPattern = locationPattern + PRIVILEGE_RESOURCE_SUFFIX;
    }


    public SortedSet<Privilege> readPrivilege() throws IOException, ClassNotFoundException {

        SortedSet<Privilege> privilegeSet =
                new TreeSet<Privilege>(new Comparator<Privilege>() {

                    public int compare(Privilege o1, Privilege o2) {

                        int tmp = o1.value().compareTo(o2.value());
                        if (tmp == 0) {
                            return Boolean.valueOf(o1.isEntrance()).compareTo(o2.isEntrance());
                        } else {
                            return tmp;
                        }
                    }
                });

        Resource[] resources = RESOLVER.getResources(locationPattern);

        for (Resource res : resources) {

            MetadataReader meta = READER_FACTORY.getMetadataReader(res);
            Class clazz = Class.forName(meta.getClassMetadata().getClassName());
            Method[] methods = clazz.getDeclaredMethods();

            for (Method method : methods) {

                Annotation[] annotations = method.getDeclaredAnnotations();
                for (Annotation annotation : annotations) {
                    if (annotation instanceof Privilege) {
                        privilegeSet.add((Privilege) annotation);
                        break;
                    }
                }
            }
        }
        return privilegeSet;
    }
}
